package com.bls.service.impl;

import com.bls.action.BLSAction;
import com.bls.constant.ResultCodeEnum;
import com.bls.entity.vo.RunScriptVo;
import com.bls.exception.MyException;
import com.bls.executor.Executor;
import com.bls.executor.parser.V3Lexer;
import com.bls.executor.parser.V3Parser;
import com.bls.service.ScriptService;
import com.bls.utils.R;
import com.bls.utils.ThrowingErrorListener;
import com.bls.utils.TreeUtils;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;

import java.sql.Connection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class ScriptServiceImpl implements ScriptService {
    Connection dbConnection = null;

    {
        try {
            dbConnection = BLSAction.getDBConnection();
        }catch (Exception e){
            System.out.println(e.getCause());
            e.printStackTrace();
        }
    }


    @Override
    public Map<String,Object> runScript(List<RunScriptVo> scriptsList, long bandId, long scriptId) {
        int index = -1;
        Map<String,Object> result = new HashMap<>();
        HashMap<String, String> map = new HashMap<>();
        try {
            for (RunScriptVo item : scriptsList) {
                index += 1;
                // todo scriptRunningMsg 包含四个信息：执行结果；异常信息；异步任务；中间结果（暂时未写）
                Map<String, Object> scriptRunningMsg = Executor.runScript(item.getScript(),new HashMap<>(),scriptId);
                if(scriptRunningMsg.containsKey("exception")){
                    MyException e = (MyException) scriptRunningMsg.get("exception");
                    map.put(scriptsList.get(index).getLine(),"运行失败");
                    result.put("results",map);
                    result.put("success",false);
                    result.put("scriptId",scriptId);
                    result.put("scriptCode",e.getErrCode());
                    result.put("scriptMessage",e.getMessage());
                    result.put("errorScriptText",scriptsList.get(index).getScript());
                    result.put("errorScriptLine",scriptsList.get(index).getLine());
                    return result;
                }
                map.put(item.getLine(), "运行结果：剧本(" + item.getScript() + ") 运行成功, 结果为: " + scriptRunningMsg.get("runResult"));
            }
        }catch (MyException e){
            map.put(scriptsList.get(index).getLine(),"运行失败:"+e.getDetail());
            result.put("results",map);
            result.put("success",false);
            result.put("scriptId",scriptId);
            result.put("scriptCode",e.getErrCode());
            result.put("scriptMessage",e.getMessage());
            result.put("errorScriptText",scriptsList.get(index).getScript());
            result.put("errorScriptLine",scriptsList.get(index).getLine());
            return result;
        }
        result.put("results",map);
        result.put("success",true);
        result.put("scriptId",scriptId);
        result.put("scriptCode",ResultCodeEnum.RUN_SUCCESS.getCode());
        result.put("scriptMessage",ResultCodeEnum.RUN_SUCCESS.getMsg());
        result.put("errorScriptText",null);
        result.put("errorScriptLine",null);
        return result;
    }

    @Override
    public Map<String,Object> deBugScript(List<RunScriptVo> scriptsList, long bandId, long scriptId) {
        int index = -1;
        Map<String,Object> result = new HashMap<>();
        HashMap<String, String> map = new HashMap<>();
        try {
            for (RunScriptVo item : scriptsList) {
                index += 1;
                // todo scriptRunningMsg 包含四个信息：执行结果；异常信息；异步任务；中间结果（暂时未写）
                Map<String, Object> scriptRunningMsg = Executor.runScript(item.getScript(), new HashMap<>(), scriptId);
                if(scriptRunningMsg.containsKey("exception")){
                    MyException e = (MyException) scriptRunningMsg.get("exception");
                    map.put(scriptsList.get(index).getLine(),"调试失败");
                    result.put("results",map);
                    result.put("success",false);
                    result.put("scriptId",scriptId);
                    result.put("scriptCode",e.getErrCode());
                    result.put("scriptMessage",e.getMessage());
                    result.put("errorScriptText",scriptsList.get(index).getScript());
                    result.put("errorScriptLine",scriptsList.get(index).getLine());
                    return result;
                }
                map.put(item.getLine(), "调试结果：剧本(" + item.getScript() + ") 调试成功, 结果为: " + scriptRunningMsg.get("runResult"));
            }
        }catch (MyException e){
            map.put(scriptsList.get(index).getLine(),"调试失败:"+e.getDetail());
            result.put("results",map);
            result.put("success",false);
            result.put("scriptId",-1);
            result.put("scriptCode",e.getErrCode());
            result.put("scriptMessage",e.getMessage());
            result.put("errorScriptText",scriptsList.get(index).getScript());
            result.put("errorScriptLine",scriptsList.get(index).getLine());
            return result;
        }
        result.put("results",map);
        result.put("success",true);
        result.put("scriptId",-1);
        result.put("scriptCode",ResultCodeEnum.DEBUG_SUCCESS.getCode());
        result.put("scriptMessage",ResultCodeEnum.DEBUG_SUCCESS.getMsg());
        result.put("errorScriptText",null);
        result.put("errorScriptLine",null);
        return result;
    }

    @Override
    public Map<String,Object> showAST(List<RunScriptVo> scriptsList, long bandId) {
        ParseTree parseTree = null;
        Map<String,Object> result =new HashMap<>();
        for (RunScriptVo item :scriptsList){
            String script = item.getScript();
            // todo script.trim()不对，要改
            V3Parser parser = getParser(script.trim());
            parser.removeErrorListeners();
            try {
                parser.addErrorListener(ThrowingErrorListener.INSTANCE);
                parseTree = parser.script();
                result.put(item.getLine(), TreeUtils.printSyntaxTree(parser, parseTree)) ;
            }catch (Exception e){
                result.put("success",false);
                result.put("errorParseLine",item.getLine());
                result.put("errorParseText","剧本解析语法树失败:"+e.getCause());
                return result;
            }
        }
        result.put("success",true);
        result.put("errorParseLine",null);
        result.put("errorParseText",null);
        return result;
    }

    private V3Parser getParser(String script){
        CharStream input = CharStreams.fromString(script);
        V3Lexer lexer = new V3Lexer(input);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        V3Parser parser = new V3Parser(tokens);
        return parser;
    }
}
